<template>
  <div class="cfs-table-component">
    <div class="cfs-table-wrapper">
      <!-- 表头部分 - 固定在顶部 -->
      <div ref="headerRef" class="cfs-table-header-wrapper" v-if="maxHeight">
        <table :class="['cfs-table', { 'cfs-table-border': border }]">
          <colgroup>
            <col
              v-for="(col, index) in columns"
              :key="index"
              :width="col.width ? `${col.width}` : 'auto'"
              class="cfs-table-col"
            />
          </colgroup>
          <thead>
            <tr>
              <th
                v-for="(col, index) in columns"
                :key="index"
                :class="getColumnClass(col)"
                :style="getColumnStyle(col, index)"
              >
                {{ col.label }}
              </th>
            </tr>
          </thead>
        </table>
      </div>

      <!-- 滚动容器和滚动条的包装器 -->
      <div
        class="scroll-container-wrapper"
        :style="{ height: maxHeight ? `${maxHeight}px` : 'auto' }"
      >
        <!-- 滚动容器 -->
        <div
          ref="scrollContainer"
          class="cfs-table-scroll-container"
          :class="{ 'has-max-height': !!maxHeight }"
          @scroll="handleScroll"
        >
          <!-- 虚拟滚动内容 -->
          <div
            v-if="maxHeight"
            :style="{ height: `${totalHeight}px`, position: 'relative' }"
          >
            <table
              :class="['cfs-table', { 'cfs-table-border': border }]"
              :style="{ transform: `translateY(${offsetY}px)`, width: '100%' }"
            >
              <colgroup>
                <col
                  v-for="(col, index) in columns"
                  :key="index"
                  :width="col.width ? `${col.width}` : 'auto'"
                  class="cfs-table-col"
                />
              </colgroup>
              <tbody>
                <tr
                  v-for="(row, rowIndex) in visibleData"
                  :key="startIndex + rowIndex"
                >
                  <td
                    v-for="(col, colIndex) in columns"
                    :key="`${startIndex + rowIndex}-${colIndex}`"
                    :class="getColumnClass(col)"
                    :style="getColumnStyle(col, colIndex)"
                    :rowspan="getCellRowspan(startIndex + rowIndex, colIndex)"
                    :colspan="getCellColspan(startIndex + rowIndex, colIndex)"
                    v-show="!isCellHidden(startIndex + rowIndex, colIndex)"
                  >
                    <template v-if="col.type === 'index'">
                      {{ startIndex + rowIndex + 1 }}
                    </template>
                    <template v-else-if="col.slot">
                      <component
                        :is="col.slot"
                        :row="row"
                        :column="col"
                        :$index="startIndex + rowIndex"
                      />
                    </template>
                    <template v-else>
                      {{ row[col.prop] }}
                    </template>
                  </td>
                </tr>
              </tbody>
            </table>
          </div>

          <!-- 非虚拟滚动模式 -->
          <table v-else :class="['cfs-table', { 'cfs-table-border': border }]">
            <colgroup>
              <col
                v-for="(col, index) in columns"
                :key="index"
                :width="col.width ? `${col.width}` : 'auto'"
              />
            </colgroup>
            <thead>
              <tr>
                <th
                  v-for="(col, index) in columns"
                  :key="index"
                  :class="getColumnClass(col)"
                  :style="getColumnStyle(col, index)"
                >
                  {{ col.label }}
                </th>
              </tr>
            </thead>
            <tbody>
              <tr v-for="(row, rowIndex) in props.data" :key="rowIndex">
                <td
                  v-for="(col, colIndex) in columns"
                  :key="colIndex"
                  :class="getColumnClass(col)"
                  :style="getColumnStyle(col, colIndex)"
                  :rowspan="getCellRowspan(rowIndex, colIndex)"
                  :colspan="getCellColspan(rowIndex, colIndex)"
                  v-show="!isCellHidden(rowIndex, colIndex)"
                >
                  <template v-if="col.type === 'index'">
                    {{ rowIndex + 1 }}
                  </template>
                  <template v-else-if="col.slots?.default">
                    <component
                      :is="col.slots.default"
                      :row="row"
                      :column="col"
                      :$index="rowIndex"
                    />
                  </template>
                  <template v-else>
                    {{ row[col.prop] }}
                  </template>
                </td>
              </tr>
            </tbody>
          </table>
        </div>

        <!-- 自定义纵向滚动条 -->
        <div
          v-if="totalHeight > props.maxHeight"
          class="scrollbar-track vertical"
          @click="handleVerticalTrackClick"
        >
          <div
            class="scrollbar-thumb vertical"
            :style="{
              transform: `translateY(${verticalThumbPosition}px)`,
              height: `${thumbHeight}px`,
            }"
            @mousedown="startVerticalDrag"
          ></div>
        </div>

        <!-- 自定义横向滚动条 -->
        <div
          v-if="scrollWidth > scrollContainerWidth"
          class="scrollbar-track horizontal"
          @click="handleHorizontalTrackClick"
        >
          <div
            class="scrollbar-thumb horizontal"
            :style="{
              transform: `translateX(${horizontalThumbPosition}px)`,
              width: `${thumbWidthHorizontal}px`,
            }"
            @mousedown="startHorizontalDrag"
          ></div>
        </div>
      </div>
    </div>
    <div ref="footerRef" class="cfs-table-footer-wrapper">
      <table
        v-if="computedSum.length"
        :class="['cfs-table-footer', { 'cfs-table-border': border }]"
      >
        <colgroup>
          <col
            v-for="(col, index) in columns"
            :key="index"
            :width="col.width ? `${col.width}` : 'auto'"
            class="cfs-table-col"
          />
        </colgroup>
        <tfoot>
          <tr>
            <td
              v-for="(col, index) in columns"
              :key="index"
              :class="getColumnClass(col)"
              :style="getColumnStyle(col, index)"
            >
              {{ computedSum[index] }}
            </td>
          </tr>
        </tfoot>
      </table>
    </div>
    <slot></slot>
  </div>
</template>

<script setup>
import {
  ref,
  shallowRef,
  computed,
  toRefs,
  onMounted,
  onUnmounted,
  provide,
  watch,
  nextTick,
} from 'vue';
import { isEqual, isNil } from 'lodash-es';
import { registerKey } from './config.js';

const props = defineProps({
  maxHeight: {
    type: Number,
    default: 0,
  },
  data: {
    type: Array,
    default: () => [],
  },
  border: {
    type: Boolean,
    default: false,
  },
  mergeRows: {
    type: Array,
    default: () => [],
  },
  mergeColumns: {
    type: Function,
    required: false,
  },
  summaryMethod: {
    type: Function,
    required: false,
  },

  align: {
    type: String,
    default: 'left',
  },
  // 新增：允许通过props直接传递columns配置
  columns: {
    type: Array,
    default: () => [],
  },
});

const { maxHeight, border } = toRefs(props);

// 列配置 - 初始化时使用props中的columns（如果有），否则使用空数组
const columns = ref([...props.columns]);
const headerRef = shallowRef(null);
const footerRef = shallowRef(null);

/**
 * 滚动容器
 */
const scrollContainer = shallowRef(null);

/**
 * 每行高度
 */
const itemHeight = 48;

/**
 * 可渲染额外的缓冲范围基数
 */
const bufferSize = 5;

/**
 * 当前滚动的位置距离顶部的距离
 */
const scrollTop = shallowRef(0);

/**
 * 当前滚动的位置距离左侧的距离（这个用于横向滚动条位置计算）
 */
const scrollLeft = shallowRef(0);

/**
 * 表格内容的总宽度（包括滚动宽度，这个用于横向滚动条位置计算）
 */
const scrollWidth = shallowRef(0);

/**
 * 当前容器宽度（没有滚动宽度）
 */
const scrollContainerWidth = shallowRef(0);

/**
 * 是否正在拖动纵向滚动条
 */
let isDraggingVertical = false;

/**
 * 是否正在拖动横向滚动条
 */
const isDraggingHorizontal = shallowRef(false);

/**
 * 当拖动纵向滚动条时的起始鼠标位置
 */
let dragStartY = 0;

/**
 * 当拖动横向滚动条时的起始鼠标位置
 */
let dragStartX = 0;

/**
 * 当拖动纵向滚动条时的起始滚动位置，本质就是触发拖动时，scrollTop 的值
 */
let dragStartScrollTop = 0;

/**
 * 当拖动横向滚动条时的起始滚动位置，本质就是触发拖动时，scrollLeft 的值
 */
let dragStartScrollLeft = 0;

/**
 * 纵向滚动条的最小滑块高度
 */
const MIN_THUMB_HEIGHT = 10;

/**
 * 横向滚动条的最小滑块宽度
 */
const MIN_THUMB_WIDTH = 20;

/**
 * 纵向滚动条的滑块高度
 */
const thumbHeight = computed(() => {
  return Math.max(
    MIN_THUMB_HEIGHT,
    Math.min(
      props.maxHeight,
      (props.maxHeight / totalHeight.value) * props.maxHeight
    )
  );
});

/**
 * 横向滚动条的滑块宽度
 */
const thumbWidthHorizontal = computed(() => {
  return Math.max(
    MIN_THUMB_WIDTH,
    (scrollContainerWidth.value / scrollWidth.value) *
      scrollContainerWidth.value
  );
});

/**
 * 表格内容的总高度（包括滚动高度）
 */
const totalHeight = computed(() => props.data.length * itemHeight);

/**
 * 表格能够渲染的可见起始索引
 */
const startIndex = computed(() => {
  if (!props.maxHeight || typeof props.maxHeight !== 'number') {
    return 0;
  }
  // 基于滚动距离 / 行高，获得当前可见的索引位
  return Math.max(0, Math.floor(scrollTop.value / itemHeight) - bufferSize);
});

/**
 * 表格能够渲染的可见行数 = 传入的表格最大高度 / 行高
 */
const visibleCount = computed(() => Math.ceil(props.maxHeight / itemHeight));

/**
 * 表格能够渲染的可见结束索引
 */
const endIndex = computed(() => {
  if (!props.maxHeight || typeof props.maxHeight !== 'number') {
    return props.data.length;
  }

  return Math.min(
    props.data.length,
    // 基于开始索引+可见的行数得到结束索引位（这里多渲染一些缓冲范围，防止滚动时出现白屏）
    startIndex.value + visibleCount.value + bufferSize * 2
  );
});

/**
 * 表格能够渲染的可见数据
 */
const visibleData = computed(() => {
  // 基于当前滚动的起始索引和结束索引，获取可见数据
  const result = props.data.slice(startIndex.value, endIndex.value);
  console.log(
    `Visible data range: ${startIndex.value} to ${endIndex.value}, length: ${result.length}`
  );
  return result;
});

/**
 * 表格能够渲染的可见数据的偏移量
 */
const offsetY = computed(() => {
  return startIndex.value * itemHeight;
});

/**
 * 垂直滚动条滑块的偏移量
 */
const verticalThumbPosition = computed(() => {
  if (!props.maxHeight || totalHeight.value <= props.maxHeight) return 0;
  const trackHeight = props.maxHeight - thumbHeight.value;
  // 计算当前滚动范围(totalHeight.value - props.maxHeight)占总可滚动范围的比例，再乘以有效轨道高度，得到滑块的偏移量
  return (
    (scrollTop.value / (totalHeight.value - props.maxHeight)) * trackHeight
  );
});

/**
 * 横向滚动条滑块的偏移量
 */
const horizontalThumbPosition = computed(() => {
  if (
    scrollWidth.value <= scrollContainerWidth.value ||
    thumbWidthHorizontal.value === 0
  )
    return 0;
  const trackWidth = scrollContainerWidth.value - thumbWidthHorizontal.value;
  return (
    (scrollLeft.value / (scrollWidth.value - scrollContainerWidth.value)) *
    trackWidth
  );
});

/**
 * 处理纵向滚动条拖动事件
 * @param e 鼠标事件对象
 */
const handleVerticalDragInternal = (e) => {
  if (!isDraggingVertical || !scrollContainer.value) return;
  const deltaY = e.clientY - dragStartY;
  const trackHeight = props.maxHeight - thumbHeight.value;
  if (trackHeight <= 0) return;
  const ratio = (totalHeight.value - props.maxHeight) / trackHeight;
  // dragStartScrollTop 是触发拖动的那个滚动位置，deltaY 是持续拖动的距离，ratio 是拖动距离占总可滚动范围的比例
  const newScrollTop = dragStartScrollTop + deltaY * ratio;

  scrollContainer.value.scrollTop = Math.max(
    0,
    Math.min(newScrollTop, totalHeight.value - props.maxHeight)
  );
};

/**
 * 处理横向滚动条拖动事件
 * @param e 鼠标事件对象
 */
const handleHorizontalDragInternal = (e) => {
  if (!isDraggingHorizontal.value || !scrollContainer.value) return;
  const deltaX = e.clientX - dragStartX;
  const trackWidth = scrollContainerWidth.value - thumbWidthHorizontal.value;
  if (trackWidth <= 0) return;
  const ratio = (scrollWidth.value - scrollContainerWidth.value) / trackWidth;
  const newScrollLeft = dragStartScrollLeft + deltaX * ratio;
  scrollContainer.value.scrollLeft = Math.max(
    0,
    Math.min(newScrollLeft, scrollWidth.value - scrollContainerWidth.value)
  );
};

/**
 * 开始拖动纵向滚动条
 * @param e 鼠标事件对象
 */
const startVerticalDrag = (e) => {
  if (totalHeight.value <= props.maxHeight) return;
  isDraggingVertical = true;
  dragStartY = e.clientY;
  dragStartScrollTop = scrollTop.value;
  document.addEventListener('mousemove', handleVerticalDragInternal);
  document.addEventListener('mouseup', stopVerticalDrag);
};

/**
 * 停止拖动纵向滚动条
 */
const stopVerticalDrag = () => {
  isDraggingVertical = false;
  document.removeEventListener('mousemove', handleVerticalDragInternal);
  document.removeEventListener('mouseup', stopVerticalDrag);
};

/**
 * 开始拖动横向滚动条
 * @param e 鼠标事件对象
 */
const startHorizontalDrag = (e) => {
  if (scrollWidth.value <= scrollContainerWidth.value) return;
  isDraggingHorizontal.value = true;
  dragStartX = e.clientX;
  dragStartScrollLeft = scrollLeft.value;
  document.addEventListener('mousemove', handleHorizontalDragInternal);
  document.addEventListener('mouseup', stopHorizontalDrag);
};

/**
 * 停止拖动横向滚动条
 */
const stopHorizontalDrag = () => {
  isDraggingHorizontal.value = false;
  document.removeEventListener('mousemove', handleHorizontalDragInternal);
  document.removeEventListener('mouseup', stopHorizontalDrag);
};

/**
 * 垂直轨道点击事件处理函数
 * @param e 点击事件对象
 */
const handleVerticalTrackClick = (e) => {
  if (totalHeight.value <= props.maxHeight || isDraggingVertical) return;
  if (!scrollContainer.value) return;
  const track = e.currentTarget;

  const rect = track.getBoundingClientRect();
  // 点击位置到轨道顶部的距离（基于点击位置到浏览器顶部 - 轨道顶部到浏览器顶部的位置 = 点击位置到轨道顶部的距离）
  const clickY = e.clientY - rect.top;

  // 计算轨道 可点击 的有效高度（滚动条本身高度 - 滚动滑块高度）
  const trackHeight = props.maxHeight - thumbHeight.value;

  if (trackHeight <= 0) return;

  // [内容可滚动距离」与「轨道有效高度」的比值，代表：轨道上每 1px 的偏移，对应内容需要滚动的 px 数
  const ratio = (totalHeight.value - props.maxHeight) / trackHeight;

  // 计算 clickY 减去滑块本身高度的一半（中心点）的距离，对应列表内容需要滚动的 px 数
  const newScrollTop = (clickY - thumbHeight.value / 2) * ratio;

  // 滚动条滚动到新的位置（确保不超过最大滚动距离）
  scrollContainer.value.scrollTop = Math.max(
    0,
    Math.min(newScrollTop, totalHeight.value - props.maxHeight)
  );
};

/**
 * 处理横向滚动条点击事件
 * @param e 点击事件对象
 */
const handleHorizontalTrackClick = (e) => {
  if (
    scrollWidth.value <= scrollContainerWidth.value ||
    isDraggingHorizontal.value
  )
    return;
  if (!scrollContainer.value) return;
  const track = e.currentTarget;
  const rect = track.getBoundingClientRect();
  const clickX = e.clientX - rect.left;
  const trackWidth = scrollContainerWidth.value - thumbWidthHorizontal.value;
  if (trackWidth <= 0) return;
  const ratio = (scrollWidth.value - scrollContainerWidth.value) / trackWidth;
  const newScrollLeft = (clickX - thumbWidthHorizontal.value / 2) * ratio;
  scrollContainer.value.scrollLeft = Math.max(
    0,
    Math.min(newScrollLeft, scrollWidth.value - scrollContainerWidth.value)
  );
};

/**
 * 处理滚动事件，更新滚动位置
 * @param e 滚动事件对象
 */
const handleScroll = (e) => {
  const target = e.target;
  scrollTop.value = target.scrollTop;
  scrollLeft.value = target.scrollLeft;
  // 同步滚动表头的水平滚动位置
  if (headerRef.value) {
    headerRef.value.scrollLeft = target.scrollLeft;
  }
  // 同步滚动表尾的水平滚动位置
  if (footerRef.value) {
    footerRef.value.scrollLeft = target.scrollLeft;
  }

  // 滚动时重新计算合并单元格，确保可见区域的合并正确
  nextTick(() => {
    calculateMergedCells();
  });
};

/**
 * 获取列的样式，针对固定位置的列（left/right）
 * @param col 列配置对象
 * @param index 列索引
 * @returns 列的样式对象
 */
const getColumnStyle = (col, index) => {
  const style = {};

  if (col.fixed === 'left') {
    const leftOffset = columns.value
      .slice(0, index)
      .filter((c) => c.fixed === 'left')
      .reduce((sum, c) => sum + (c.width || 0), 0);
    style.position = 'sticky';
    style.left = `${leftOffset}px`;
    style.zIndex = 10;
    style.backgroundColor = '#fff';
  }

  if (col.fixed === 'right') {
    const rightFixedCols = columns.value.filter((c) => c.fixed === 'right');
    const colIndexInFixed = rightFixedCols.findIndex((c) => c === col);
    const rightOffset = rightFixedCols
      .slice(colIndexInFixed + 1)
      .reduce((sum, c) => sum + (c.width || 0), 0);
    style.position = 'sticky';
    style.right = `${rightOffset}px`;
    style.zIndex = 10;
    style.backgroundColor = '#fff';
  }
  return style;
};

// 获取列类名
const getColumnClass = (col) => {
  return {
    'cfs-table-fixed-left': col.fixed === 'left',
    'cfs-table-fixed-right': col.fixed === 'right',
  };
};

// 单元格合并相关
const mergedCells = ref(new Map());
const hiddenCells = ref(new Set());

/**
 * 获取单元格的键值，用于合并单元格的存储
 * @param rowIndex 行索引
 * @param colIndex 列索引
 * @returns 单元格的键值（格式："rowIndex-colIndex"）
 */
const getCellKey = (rowIndex, colIndex) => `${rowIndex}-${colIndex}`;

const getCellRowspan = (rowIndex, colIndex) => {
  const key = getCellKey(rowIndex, colIndex);

  return mergedCells.value.get(key)?.rowspan || 1;
};

const getCellColspan = (rowIndex, colIndex) => {
  const key = getCellKey(rowIndex, colIndex);
  return mergedCells.value.get(key)?.colspan || 1;
};

const isCellHidden = (rowIndex, colIndex) => {
  const key = getCellKey(rowIndex, colIndex);
  return hiddenCells.value.has(key);
};

/**
 * 计算合并单元格
 */
const calculateMergedCells = () => {
  mergedCells.value.clear();
  hiddenCells.value.clear();

  // 先处理行合并逻辑
  if (props.mergeRows && props.mergeRows.length > 0) {
    calculateRowMerges();
  }

  // 再处理列合并逻辑
  if (props.mergeColumns && typeof props.mergeColumns === 'function') {
    calculateColumnMerges();
  }
};

/**
 * 计算行合并
 */
const calculateRowMerges = () => {
  if (!props.mergeRows || props.mergeRows.length === 0 || !props.data.length)
    return;

  // 为每个属性单独计算合并信息，但只针对当前可见区域
  props.mergeRows.forEach((prop) => {
    const colIndex = columns.value.findIndex((col) => col.prop === prop);
    if (colIndex === -1) return;

    // 为当前属性创建合并组，只处理可见区域的数据
    const mergeGroups = [];

    // 从可见区域的起始索引开始遍历
    for (let i = startIndex.value; i < endIndex.value; i++) {
      const cellKey = getCellKey(i, colIndex);
      // 跳过已经被处理的单元格
      if (hiddenCells.value.has(cellKey)) continue;

      // 创建新的合并组
      let currentGroup = {
        // 合并组的起始索引
        startIndex: i,
        // 合并组的单元格数量
        count: 1,
        // 合并组的单元格值
        value: props.data[i][prop],
      };

      // 向后查找相同值的单元格，只在可见区域内
      let nextIndex = i + 1;
      while (nextIndex < endIndex.value) {
        const nextValue = props.data[nextIndex][prop];
        const currentValue = currentGroup.value;
        const valuesEqual =
          !isNil(currentValue) &&
          !isNil(nextValue) &&
          isEqual(currentValue, nextValue);

        if (valuesEqual) {
          currentGroup.count++;
        } else {
          break;
        }
        nextIndex++;
      }

      if (currentGroup.count > 1) {
        mergeGroups.push(currentGroup);

        // 为当前合并组设置rowspan
        const key = getCellKey(currentGroup.startIndex, colIndex);

        mergedCells.value.set(key, {
          rowspan: currentGroup.count,
          colspan: 1,
        });

        // 标记被合并的单元格为隐藏
        for (let j = 1; j < currentGroup.count; j++) {
          hiddenCells.value.add(
            getCellKey(currentGroup.startIndex + j, colIndex)
          );
        }
      }
    }
  });
};

/**
 * 计算列合并
 */
const calculateColumnMerges = () => {
  if (
    !props.mergeColumns ||
    typeof props.mergeColumns !== 'function' ||
    !props.data.length
  )
    return;

  // 调用mergeColumns回调函数获取合并配置
  const mergeConfig = props.mergeColumns(props.data);

  if (!mergeConfig || !Array.isArray(mergeConfig) || mergeConfig.length !== 2)
    return;

  const [mergeProps, shouldMergeFunction] = mergeConfig;
  if (!Array.isArray(mergeProps) || typeof shouldMergeFunction !== 'function')
    return;

  // 只遍历可见区域内的数据行
  for (let rowIndex = startIndex.value; rowIndex < endIndex.value; rowIndex++) {
    // 检查当前行是否需要合并列
    if (shouldMergeFunction(rowIndex)) {
      // 找到需要合并的列的索引范围
      const startColIndex = columns.value.findIndex(
        (col) => col.prop === mergeProps[0]
      );
      const endColIndex = columns.value.findIndex(
        (col) => col.prop === mergeProps[mergeProps.length - 1]
      );

      if (
        startColIndex !== -1 &&
        endColIndex !== -1 &&
        startColIndex <= endColIndex
      ) {
        const colspan = endColIndex - startColIndex + 1;

        // 设置第一个单元格的colspan
        const key = getCellKey(rowIndex, startColIndex);
        // 检查单元格是否已经被隐藏
        if (!hiddenCells.value.has(key)) {
          const existingMerge = mergedCells.value.get(key) || {
            rowspan: 1,
            colspan: 1,
          };
          mergedCells.value.set(key, {
            ...existingMerge,
            colspan: colspan,
          });

          for (let j = startColIndex + 1; j <= endColIndex; j++) {
            const cellKey = getCellKey(rowIndex, j);
            if (!hiddenCells.value.has(cellKey)) {
              hiddenCells.value.add(cellKey);
            }
          }
        }
      }
    }
  }
};

/**
 * 计算表格的汇总行数据
 */
const computedSum = computed(() => {
  if (!props.data.length) return [];
  if (props.summaryMethod && typeof props.summaryMethod === 'function') {
    return props.summaryMethod({
      columns: columns.value,
      data: props.data,
    });
  }

  return [];
});

// 注册列
const registerColumn = (column) => {
  if (props.columns?.length) return;
  columns.value.push(column);
};

provide(registerKey, registerColumn);

defineExpose({});

onMounted(() => {
  if (scrollContainer.value) {
    scrollWidth.value = scrollContainer.value.scrollWidth;
    scrollContainerWidth.value = scrollContainer.value.clientWidth;

    const resizeObserver = new ResizeObserver(() => {
      if (scrollContainer.value) {
        scrollWidth.value = scrollContainer.value.scrollWidth;
        scrollContainerWidth.value = scrollContainer.value.clientWidth;
      }
    });

    // 监听滚动容器的变化
    resizeObserver.observe(scrollContainer.value);
  }
});

onUnmounted(() => {
  document.removeEventListener('mousemove', handleVerticalDragInternal);
  document.removeEventListener('mouseup', stopVerticalDrag);
  document.removeEventListener('mousemove', handleHorizontalDragInternal);
  document.removeEventListener('mouseup', stopHorizontalDrag);
});

watch(
  () => props.data,
  () => {
    nextTick(() => {
      calculateMergedCells();
    });
  },
  { deep: true, immediate: true }
);
</script>

<style scoped lang="less">
.cfs-table-component {
  width: 100%;
  overflow: hidden;
  position: relative;
}
.cfs-table-wrapper {
  width: 100%;
  overflow: hidden;
  position: relative;
}

.cfs-table-header-wrapper {
  overflow: hidden;
  border-bottom: 1px solid #ebeef5;
  position: relative;
}

.cfs-table-header-wrapper .cfs-table {
  border-collapse: collapse;
  width: 100%;
}

.scroll-container-wrapper {
  position: relative;
  width: 100%;
}

.cfs-table-scroll-container {
  width: 100%;
  height: 100%;
  overflow-x: auto;
  overflow-y: auto;
  position: relative;
}

.cfs-table-scroll-container.has-max-height {
  overflow-y: auto;
  position: relative;
}

.cfs-table {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
}

.cfs-table-col {
  min-width: 50px;
}

.cfs-table th,
.cfs-table td {
  padding: 8px 12px;
  text-align: left;
  background-color: #fff;
  height: 48px;
  word-break: break-all;
}

.cfs-table th {
  font-weight: 600;
  background-color: #f8f8f8;
}

.cfs-table-border {
  border: 1px solid #ebeef5;
}

.cfs-table-border th,
.cfs-table-border td {
  border: 1px solid #ebeef5;
}

.cfs-table-fixed-left,
.cfs-table-fixed-right {
  box-shadow: 2px 0 4px rgba(0, 0, 0, 0.1);
}

.cfs-table-fixed-right {
  box-shadow: -2px 0 4px rgba(0, 0, 0, 0.1);
}

.cfs-table tbody tr:hover td {
  background-color: #f5f7fa;
}

.scrollbar-track {
  position: absolute;
  z-index: 9;
  border-radius: 4px;
  transition: background-color 0.3s ease;

  &:hover {
    user-select: none;
  }

  .scrollbar-thumb {
    position: absolute;
    cursor: pointer;
    border-radius: inherit;
    background-color: #d6d8dd;
    transition: background-color 0.3s ease;

    &:hover {
      background-color: #c7c8cb;
    }
  }

  .vertical {
    width: 6px;
  }

  .horizontal {
    height: 6px;
  }
}

.scrollbar-track.vertical {
  width: 8px;
  height: 100%;
  top: 0;
  right: 0;
}

.scrollbar-track.horizontal {
  height: 8px;
  width: 100%;
  bottom: 0;
  left: 0;
}

.cfs-table-footer-wrapper {
  overflow: hidden;
  border-bottom: 1px solid #ebeef5;
  position: relative;
}

.cfs-table-footer {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
  background-color: #f5f8ff;

  td {
    height: 48px;
    padding: 8px 12px;
  }
}

/* 隐藏原生滚动条 */
::-webkit-scrollbar {
  display: none;
}

::-webkit-scrollbar-thumb {
  background-color: transparent;
}

::-webkit-scrollbar-thumb:hover {
  background-color: transparent;
}
</style>
